package com.studykun.client.model;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.studykun.client.model.js.JsSyllabus;
import com.studykun.client.util.ObservableArrayList;
import com.studykun.client.util.ObservableList;

public class Syllabus {
  private ObservableList<Deck> decks_ = new ObservableArrayList<Deck>();
  
  public Syllabus(
      final JsSyllabus jsSyllabus) {
    final int syllabusLength = jsSyllabus.length();
    
    for (int i = 0; i < syllabusLength; ++i) {
      decks_.add(new Deck(jsSyllabus.get(i)));
    }
  }
  
  public Syllabus() {
  }
  
  public void synchronise(
      final Syllabus syllabus) {
    // TODO: Use a property journal instead.
    decks_.addAll(syllabus.decks());
  }

  public ObservableList<Deck> decks() {
    return decks_;
  }

  public final ArrayList<ArrayList<Card>> buckets() {
    final ArrayList<ArrayList<Card>> buckets = new ArrayList<ArrayList<Card>>();
    for (int i = 0; i < 5; ++i) {
      buckets.add(new ArrayList<Card>());
    }
    for (final Deck deck : decks_) {
      for (final Card card : deck.cards()) {
        if (card.selected()) {
          buckets.get(card.progress()).add(card);
        }
      }
    }
    return buckets;
  }

  public final List<Integer> getProgress() {
    final ArrayList<Integer> buckets = new ArrayList<Integer>();
    for (int i = 0; i < 5; ++i) {
      buckets.add(0);
    }
    for (final Deck deck : decks_) {
      for (final Card card : deck.cards()) {
        if (card.selected()) {
          final int index = card.progress();
          buckets.set(index, buckets.get(index) + 1);
        }
      }
    }
    return buckets;
  }
  
  public final int cardCount() {
    int total = 0;
    for (final Deck deck : decks_) {
      total += deck.cards().size();
    }
    return total;
  }

  public interface DownloadCallback
  {
    public void onError(
        final Request request,
        final Response response,
        final Throwable throwable);
    
    public void onDownload(
        final Syllabus syllabus);
  }

  public final static void dowloadFrom(
      final String url,
      final DownloadCallback downloadCallback)
  {
    final Syllabus syllabus =
      new Syllabus(JsSyllabus.fromJson(SyllabusStatic.syllabus));
    
    downloadCallback.onDownload(syllabus);
    
    if (syllabus != null) {
      return;
    }
    
    // Send request to server and catch any errors.
    final RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);

    try {
      builder.sendRequest(null, new RequestCallback() {
        public void onError(Request request, Throwable exception) {
          downloadCallback.onError(request, null, exception);
        }

        public void onResponseReceived(Request request, Response response) {
          if (200 == response.getStatusCode()) {
            try {
              final Syllabus syllabus =
                new Syllabus(JsSyllabus.fromJson(response.getText()));
              downloadCallback.onDownload(syllabus);
            } catch (final JavaScriptException e) {
              downloadCallback.onError(request, response, e);
            }
          } else {
            downloadCallback.onError(request, response, null);
          }
        }
      });
    } catch (final RequestException e) {
      downloadCallback.onError(null, null, e);
    }
  }
}
